﻿using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Linq;
using CodeContrib.Data.Entity;

namespace CodeContribBlog.Data
{
	public class BlogContext : DbContext
	{
		private readonly int? _blogId;
		private readonly int? _userId;

		public IDbSet<Blog> Blogs { get; set; }
		public IDbSet<Commenter> Commenters { get; set; }
		public IDbSet<Comment> Comments { get; set; }
		public IDbSet<Post> Posts { get; set; }
		public IDbSet<Tag> Tags { get; set; }
		public IDbSet<User> Users { get; set; }

		public BlogContext()
			: this(null, null)
		{
		}

		public BlogContext(int? userId = null, int? blogId = null)
		{
			_blogId = blogId;
			_userId = userId;

			Initialize();
		}

		public BlogContext(string nameOrConnectionString, int? userId = null, int? blogId = null)
			: base(nameOrConnectionString)
		{
			_blogId = blogId;
			_userId = userId;

			Initialize();
		}

		public Post FindNextPost(Post post)
		{
			return Posts.WhereIsPublic().Where(p => p.Blog.Id == post.Blog.Id && p.PublishedAt >= post.PublishedAt && p.Id != post.Id).OrderBy(p => p.PublishedAt).FirstOrDefault();
		}

		public Post FindPreviousPost(Post post)
		{
			return Posts.WhereIsPublic().Where(p => p.Blog.Id == post.Blog.Id && p.PublishedAt <= post.PublishedAt && p.Id != post.Id).OrderByDescending(p => p.PublishedAt).FirstOrDefault();
		}

		private void Initialize()
		{
			Configuration.LazyLoadingEnabled = false;

			if (_userId != null
			    && _blogId != null)
			{
				Blogs = new FilteredDbSet<Blog>(this, b => b.Creator.Id == _userId && b.Id == _blogId);
				Comments = new FilteredDbSet<Comment>(this, c => c.Post.Blog.Creator.Id == _userId && c.Post.Blog.Id == _blogId);
				Posts = new FilteredDbSet<Post>(this, p => p.Blog.Creator.Id == _userId && p.Blog.Id == _blogId, p => p.BlogId = _blogId.Value);
				Tags = new FilteredDbSet<Tag>(this, t => t.Blog.Creator.Id == _userId && t.Blog.Id == _blogId);
			}
			else if (_userId != null)
			{
				Blogs = new FilteredDbSet<Blog>(this, b => b.Creator.Id == _userId);
				Comments = new FilteredDbSet<Comment>(this, c => c.Post.Blog.Creator.Id == _userId);
				Posts = new FilteredDbSet<Post>(this, p => p.Blog.Creator.Id == _userId);
				Tags = new FilteredDbSet<Tag>(this, t => t.Blog.Creator.Id == _userId);
			}
			else if (_blogId != null)
			{
				Blogs = new FilteredDbSet<Blog>(this, b => b.Id == _blogId);
				Comments = new FilteredDbSet<Comment>(this, c => c.Post.Blog.Id == _blogId);
				Posts = new FilteredDbSet<Post>(this, p => p.Blog.Id == _blogId, p => p.BlogId = _blogId.Value);
				Tags = new FilteredDbSet<Tag>(this, t => t.Blog.Id == _blogId);
			}
		}

		protected override void OnModelCreating(DbModelBuilder modelBuilder)
		{
			base.OnModelCreating(modelBuilder);

			modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
			modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
		}
	}
}